﻿Imports System.Text
Imports Kairyu.Extension

Namespace Save

    ''' <summary>
    ''' 更新コマンド作成クラス
    ''' </summary>
    ''' <remarks></remarks>
    Friend Class UpdateCommandFactory

        Private Shared VALUE_PARAMETER_PREFIX As String = "VP"

        Private Shared WHERE_PARAMETER_PREFIX As String = "WP"

        ''' <summary>
        ''' 更新コマンドを生成します
        ''' </summary>
        ''' <param name="def"></param>
        ''' <param name="trn"></param>
        ''' <param name="prefix"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Function Create(ByVal def As SaveDefinition, ByVal trn As IDbTransaction, ByVal prefix As String) As IDbCommand
            Return (New Core).CreateCommand(def, trn, prefix)
        End Function

        Private Class Core

            Private Property Definition As SaveDefinition

            Private Property Command As IDbCommand

            Private Property Prefix As String

            Public Function CreateCommand(ByVal def As SaveDefinition, ByVal trn As IDbTransaction, ByVal prefix As String) As IDbCommand
                Me.Definition = def
                Me.Prefix = prefix

                Me.Command = trn.Connection.CreateCommand
                Me.Command.Transaction = trn

                Me.BuildCommand()

                Return Me.Command
            End Function

            Private Sub BuildCommand()
                Dim valueText As New StringBuilder
                Dim whereText As New StringBuilder
                Dim valueCnt As Integer = 0
                Dim whereCnt As Integer = 0

                '値パラメータの追加、生成
                Dim addValueParameter As Func(Of Object, Type, String) =
                    Function(val As Object, t As Type) As String
                        Dim prm As IDbDataParameter = Me.Command.CreateParameter
                        If t.FullName = "System.Byte[]" Then prm.DbType = DbType.Binary
                        prm.ParameterName = UpdateCommandFactory.VALUE_PARAMETER_PREFIX & valueCnt
                        prm.Value = If(val Is Nothing, DBNull.Value, val)
                        Me.Command.Parameters.Add(prm)
                        valueCnt += 1
                        Return Me.Prefix & prm.ParameterName
                    End Function

                '値文字列の追加
                Dim addValueCommand As Action(Of String) =
                    Sub(text As String)
                        valueText.AppendDelimiter(", ")
                        valueText.Append(text)
                    End Sub

                '検索パラメータの追加、生成
                Dim addWhereParameter As Func(Of Object, String) =
                    Function(val As Object) As String
                        Dim prm As IDbDataParameter = Me.Command.CreateParameter
                        prm.ParameterName = UpdateCommandFactory.WHERE_PARAMETER_PREFIX & whereCnt
                        prm.Value = If(val Is Nothing, DBNull.Value, val)
                        Me.Command.Parameters.Add(prm)
                        whereCnt += 1
                        Return Me.Prefix & prm.ParameterName
                    End Function

                'コマンド文字列の追加
                Dim addWhereCommand As Action(Of String) =
                    Sub(text As String)
                        whereText.Appenddelimiter(" AND ")
                        whereText.Append(text)
                    End Sub

                '列属性に更新値の作成を作成させる
                For Each item In Me.Definition.TableArchive.ColumnArchives.Select(Function(x) x.Value)
                    Dim arch As ColumnArchive = item
                    Dim c As ColumnAttribute = arch.GetColumnAttribute
                    c.BuildUpdateColumnCommand(Me.Definition.Model, item.ArchiveValue, addValueCommand, addValueParameter)
                    c.BuildSaveWhereCommand(Me.Definition.Model, item.ArchiveValue, addWhereCommand, addWhereParameter)
                Next

                Me.Command.CommandText = String.Format("UPDATE {0} SET {1} WHERE {2}", Me.Definition.TableAttribute.TableFullName, valueText.ToString, whereText.ToString)
            End Sub

        End Class

    End Class

End Namespace

